package com.edu.exam.entity.system.config;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

/**
 * 试题替换实体类
 *
 * <p>试题替换实体用于记录试题替换操作的详细信息，包括替换前后的试题信息、
 * 替换原因、相似度评分、质量影响分析等。支持智能推荐、批量替换、历史追溯等功能。</p>
 *
 * <p>核心功能：
 * - 替换记录：记录试题替换的完整信息
 * - 相似度分析：分析替换试题与原试题的相似度
 * - 质量评估：评估替换操作对试卷质量的影响
 * - 历史管理：支持替换历史的管理和回滚</p>
 *
 * @author 系统生成
 * @version 2.0
 * @since 2025-11-09
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(AuditingEntityListener.class)
public class QuestionReplacement {

    /**
     * 主键ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 替换ID
     *
     * <p>试题替换操作的唯一标识符，采用UUID格式生成。
     * 用于替换操作的唯一标识和结果追踪。</p>
     */
    @Column(name = "replacement_id", nullable = false, length = 32, unique = true)
    private String replacementId;

    /**
     * 原试题ID
     *
     * <p>被替换试题的唯一标识符。
     * 记录被替换出试卷的试题ID。</p>
     */
    @Column(name = "original_question_id", nullable = false, length = 32)
    private String originalQuestionId;

    /**
     * 替换试题ID
     *
     * <p>替换试题的唯一标识符。
     * 记录替换进试卷的试题ID。</p>
     */
    @Column(name = "replacement_question_id", nullable = false, length = 32)
    private String replacementQuestionId;

    /**
     * 试卷ID
     *
     * <p>所属试卷的唯一标识符。
     * 标识替换操作所属的试卷。</p>
     */
    @Column(name = "paper_id", nullable = false, length = 32)
    private String paperId;

    /**
     * 替换策略
     *
     * <p>替换操作的策略类型，用于区分不同的替换方式。
     * 支持的策略包括：MANUAL（手动选择）、AUTO_RECOMMEND（自动推荐）、SIMILARITY_MATCH（相似度匹配）等。</p>
     */
    @Column(name = "replacement_strategy", nullable = false, length = 30)
    private String replacementStrategy;

    /**
     * 替换原因
     *
     * <p>执行替换操作的原因说明。
     * 记录替换的具体原因和背景信息。</p>
     */
    @Column(name = "replacement_reason", length = 500)
    private String replacementReason;

    /**
     * 相似度评分
     *
     * <p>替换试题与原试题的相似度评分，取值范围0-100。
     * 基于内容、难度、知识点等多个维度计算得出。</p>
     */
    @Column(name = "similarity_score", precision = 5, scale = 2)
    private Double similarityScore;

    /**
     * 难度差异
     *
     * <p>替换试题与原试题的难度差异值。
     * 正值表示替换试题难度更高，负值表示难度更低。</p>
     */
    @Column(name = "difficulty_difference", precision = 3, scale = 2)
    private Double difficultyDifference;

    /**
     * 分值差异
     *
     * <p>替换试题与原试题的分值差异值。
     * 正值表示替换试题分值更高，负值表示分值更低。</p>
     */
    @Column(name = "score_difference", precision = 5, scale = 2)
    private Double scoreDifference;

    /**
     * 影响分析
     *
     * <p>JSON格式的替换影响分析结果。
     * 包含对试卷整体质量、知识点覆盖、难度分布等影响的分析。</p>
     */
    @Column(name = "impact_analysis", columnDefinition = "TEXT")
    private String impactAnalysis;

    /**
     * 替换状态
     *
     * <p>替换操作的状态标识。
     * 支持的状态包括：PENDING（待确认）、CONFIRMED（已确认）、APPLIED（已应用）、REVERTED（已回滚）、FAILED（失败）等。</p>
     */
    @Column(name = "replacement_status", nullable = false, length = 20)
    private String replacementStatus = "PENDING";

    /**
     * 操作者ID
     *
     * <p>执行替换操作的用户ID，关联系统用户表。
     * 用于记录替换操作的责任人和权限控制。</p>
     */
    @Column(name = "operator_id", nullable = false, length = 32)
    private String operatorId;

    /**
     * 操作者姓名
     *
     * <p>执行替换操作的用户姓名，用于显示和记录。
     * 冗余存储用户姓名，避免频繁关联查询用户表。</p>
     */
    @Column(name = "operator_name", nullable = false, length = 100)
    private String operatorName;

    /**
     * 替换时间
     *
     * <p>替换操作的执行时间，记录具体的替换时间点。
     * 用于替换操作的时间跟踪和分析。</p>
     */
    @Column(name = "replacement_time", nullable = false)
    private LocalDateTime replacementTime;

    /**
     * 应用时间
     *
     * <p>替换操作应用到试卷的时间。
     * 记录替换操作实际生效的时间。</p>
     */
    @Column(name = "applied_time")
    private LocalDateTime appliedTime;

    /**
     * 推荐理由
     *
     * <p>智能推荐时的推荐理由说明。
     * 详细说明为什么推荐该替换试题。</p>
     */
    @Column(name = "recommendation_reason", length = 1000)
    private String recommendationReason;

    /**
     * 是否批量替换
     *
     * <p>标识是否为批量替换操作的一部分。
     * true表示批量替换，false表示单个替换。</p>
     */
    @Column(name = "is_batch_replacement", nullable = false)
    private Boolean isBatchReplacement = false;

    /**
     * 批次ID
     *
     * <p>批量替换操作的批次标识符。
     * 用于关联同一批次中的多个替换操作。</p>
     */
    @Column(name = "batch_id", length = 32)
    private String batchId;

    /**
     * 质量评分变化
     *
     * <p>替换操作后试卷质量评分的变化值。
     * 正值表示质量提升，负值表示质量下降。</p>
     */
    @Column(name = "quality_score_change", precision = 5, scale = 2)
    private Double qualityScoreChange;

    /**
     * 约束条件检查结果
     *
     * <p>JSON格式的约束条件检查结果。
     * 记录替换操作是否满足相关的约束条件。</p>
     */
    @Column(name = "constraint_check_result", columnDefinition = "TEXT")
    private String constraintCheckResult;

    /**
     * 是否已回滚
     *
     * <p>标识替换操作是否已经回滚。
     * true表示已回滚，false表示未回滚。</p>
     */
    @Column(name = "is_reverted", nullable = false)
    private Boolean isReverted = false;

    /**
     * 回滚时间
     *
     * <p>替换操作回滚的时间。
     * 记录回滚操作的具体时间点。</p>
     */
    @Column(name = "revert_time")
    private LocalDateTime revertTime;

    /**
     * 回滚原因
     *
     * <p>执行回滚操作的原因说明。
     * 记录回滚的具体原因和背景信息。</p>
     */
    @Column(name = "revert_reason", length = 500)
    private String revertReason;

    // ===== 审计字段 =====

    /**
     * 创建时间
     */
    @CreatedDate
    @Column(name = "create_time", nullable = false, updatable = false)
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    @LastModifiedDate
    @Column(name = "update_time", nullable = false)
    private LocalDateTime updateTime;

    // ===== 常量定义 =====

    // 替换策略常量
    /** 替换策略 - 手动选择 */
    public static final String STRATEGY_MANUAL = "MANUAL";

    /** 替换策略 - 自动推荐 */
    public static final String STRATEGY_AUTO_RECOMMEND = "AUTO_RECOMMEND";

    /** 替换策略 - 相似度匹配 */
    public static final String STRATEGY_SIMILARITY_MATCH = "SIMILARITY_MATCH";

    /** 替换策略 - 随机选择 */
    public static final String STRATEGY_RANDOM = "RANDOM";

    // 替换状态常量
    /** 替换状态 - 待确认 */
    public static final String STATUS_PENDING = "PENDING";

    /** 替换状态 - 已确认 */
    public static final String STATUS_CONFIRMED = "CONFIRMED";

    /** 替换状态 - 已应用 */
    public static final String STATUS_APPLIED = "APPLIED";

    /** 替换状态 - 已回滚 */
    public static final String STATUS_REVERTED = "REVERTED";

    /** 替换状态 - 失败 */
    public static final String STATUS_FAILED = "FAILED";

    // 相似度等级常量
    /** 相似度等级 - 高相似 */
    public static final Double SIMILARITY_HIGH = 90.0;

    /** 相似度等级 - 中等相似 */
    public static final Double SIMILARITY_MEDIUM = 70.0;

    /** 相似度等级 - 低相似 */
    public static final Double SIMILARITY_LOW = 50.0;

}